home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Merciful 2
/
Merciful - Disc 2.iso
/
software
/
d
/
devioustools19.dms
/
devioustools19.adf
/
utils
/
005.lzx
/
CompactPlayer
/
Source
/
scsi.c
< prev
next >
Wrap
C/C++ Source or Header
|
1978-01-22
|
9KB
|
430 lines
#include "sysheaders.h"
#include "cdpanel.h"
#include "CompactPlayer.h"
/********************************************************
* SCSI
*/
struct MsgPort *SCSIPort;
struct IOStdReq *SCSIIO;
STRPTR Device = "scsi.device";
ULONG Unit = 6;
UBYTE *DataBuf;
UBYTE *TOCBuf;
UBYTE *SenseData;
BOOL Ejected = FALSE;
BOOL JustStarted = FALSE;
//#define SINGLE_TRACK_PLAY 1
#define BLOCKSPERSECOND 75 /* CD blocks per second of audio */
int __stdargs
Open_SCSI(void)
{
if ((DataBuf = AllocVec(DATA_LEN, MEMF_CHIP | MEMF_CLEAR)) &&
(TOCBuf = AllocVec(TOC_LEN, MEMF_CHIP)) &&
(SenseData = AllocVec(SENSE_LEN, MEMF_CHIP | MEMF_CLEAR)) &&
(SCSIPort = CreateMsgPort()) &&
(SCSIIO = CreateIORequest(SCSIPort, sizeof(struct IOStdReq))) &&
!OpenDevice(Device, Unit, (struct IORequest *) SCSIIO, NULL))
{
SCSIIO->io_Command = HD_SCSICMD;
CD_Eject = Eject_SCSI;
CD_Stop = Stop_SCSI;
CD_Play = Play_SCSI;
CD_PauseResume = PauseResume_SCSI;
CD_Seek = Seek_SCSI;
CD_Snoop = Snoop_SCSI;
CD_ReadTOC = ReadTOC_SCSI;
CD_IsCD = IsCD_SCSI;
CD_Close = (void (*)(void))Close_SCSI;
if (CD_IsCD())
return 0;
else
ErrorMsg(GS(DEVICE_FAIL), Device, Unit);
}
else
ErrorMsg(GS(SCSI_FAIL), Device, Unit);
Close_SCSI();
return -1;
}
void __stdargs
Close_SCSI(void)
{
if (SCSIIO)
{
if (SCSIIO->io_Command == HD_SCSICMD)
CloseDevice((struct IORequest *) SCSIIO);
DeleteIORequest(SCSIIO);
SCSIIO = NULL;
}
if (SCSIPort)
{
DeleteMsgPort(SCSIPort);
SCSIPort = NULL;
}
if (SenseData)
{
FreeVec(SenseData);
SenseData = NULL;
}
if (TOCBuf)
{
FreeVec(TOCBuf);
TOCBuf = NULL;
}
if (DataBuf)
{
FreeVec(DataBuf);
DataBuf = NULL;
}
CD_Eject = (void (*)(UBYTE))Dummy;
CD_Stop = (void (*)(void))Dummy;
CD_Play = (void (*)(ULONG))Dummy;
CD_PauseResume = (void (*)(UBYTE))Dummy;
CD_Seek = (void (*)(LONG))Dummy;
CD_Snoop = (ULONG (*)(ULONG *, ULONG *, ULONG *, ULONG))Dummy;
CD_ReadTOC = (ULONG (*)(void))Dummy;
CD_IsCD = (BOOL (*)(void))Dummy;
CD_Close = (void (*)(void))Dummy;
}
static int
DoSCSI( APTR data, int dsize, APTR cmd, int csize, UBYTE flags )
{
if (SCSIIO)
{
static struct SCSICmd ScsiCmd;
/* send a SCSI Direct command */
ScsiCmd.scsi_Command = cmd;
ScsiCmd.scsi_CmdLength = csize;
ScsiCmd.scsi_Data = data;
ScsiCmd.scsi_Length = dsize;
ScsiCmd.scsi_SenseData = SenseData;
ScsiCmd.scsi_SenseLength = SENSE_LEN;
ScsiCmd.scsi_SenseActual = 0;
ScsiCmd.scsi_Flags = flags;
SCSIIO->io_Command = HD_SCSICMD;
SCSIIO->io_Data = &ScsiCmd;
SCSIIO->io_Length = sizeof(ScsiCmd);
DoIO((struct IORequest *)SCSIIO);
return SCSIIO->io_Error;
}
return -1;
}
void
Eject_SCSI( UBYTE out )
{
static SCSICMD6 command = { SCSI_DA_START_STOP_UNIT };
/* Eject/Reload a CD */
command.b4 = out ? 0x02 : 0x03;
Ejected = out;
DoSCSI( NULL, 0, &command, sizeof(command), (SCSIF_READ|SCSIF_AUTOSENSE) );
}
void
Stop_SCSI(void)
{
static SCSICMD6 command = { SCSI_DA_START_STOP_UNIT };
/* Stop motor */
DoSCSI( NULL, 0, &command, sizeof(command), (SCSIF_READ|SCSIF_AUTOSENSE) );
}
#ifndef SINGLE_TRACK_PLAY
ULONG EndAddress = ~0;
#endif
void
Play_SCSI(ULONG track)
{
static SCSICMD12 command = { SCSI_CD_PLAY_AUDIO_12 };
ULONG address, length;
/* Play a track. Basic program (random order) support in here, even
* though there is no program editor yet. */
if (TOCP[0] != ~0)
{
if (TOCP[track] == ~0)
return;
address = TOCL[TOCP[track-1]]+1;
}
else
{
if (track > Tracks)
return;
address = TOCL[track-1]+1;
}
Track = track;
command.b2 = (address & 0xff000000) >> 24;
command.b3 = (address & 0x00ff0000) >> 16;
command.b4 = (address & 0x0000ff00) >> 8;
command.b5 = (address & 0x000000ff);
#ifdef SINGLE_TRACK_PLAY
if (TOCP[0] != ~0)
length = TOCL[TOCP[track]] - address - 1;
else
length = TOCL[Tracks-1] - address - 1;
command.b6 = (length & 0xff000000) >> 24;
command.b7 = (length & 0x00ff0000) >> 16;
command.b8 = (length & 0x0000ff00) >> 8;
command.b9 = (length & 0x000000ff);
#else
/* continuous play */
if (TOCP[0] != ~0)
EndAddress = TOCL[TOCP[track]] - 1;
else
EndAddress = ~0;
command.b6 = 0xff;
command.b7 = 0xff;
command.b8 = 0xff;
command.b9 = 0xff;
#endif
/* because a Toshiba XM3601B can abort a PLAY_AUDIO sent immediately
* after media change without any error code, we have a kludge that makes
* it restart. */
JustStarted = TRUE;
DoSCSI( DataBuf, DATA_LEN, &command, sizeof(command), (SCSIF_READ|SCSIF_AUTOSENSE) );
}
void
PauseResume_SCSI( UBYTE pause )
{
static SCSICMD10 command = { SCSI_CD_PAUSE_RESUME };
/* Pause/Restart playing */
command.b8 = pause;
DoSCSI( NULL, 0, &command, sizeof(command), (SCSIF_READ|SCSIF_AUTOSENSE) );
}
void
Seek_SCSI( LONG seconds )
{
static SCSICMD10 command = { SCSI_CD_READ_SUB_CHANNEL };
command.b2 = 0x40;
command.b3 = 1;
command.b6 = 0;
command.b7 = 255;
command.b8 = 255;
/* Seek forward/backward (rewind/fast forward) */
if (!DoSCSI( DataBuf, DATA_LEN, &command, sizeof(command), (SCSIF_READ|SCSIF_AUTOSENSE) ))
{
static SCSICMD12 command = { SCSI_CD_PLAY_AUDIO_12 };
ULONG address = (DataBuf[8] << 24 | DataBuf[9] << 16 | DataBuf[10] << 8 | DataBuf[11]);
ULONG length, start, end;
address += seconds * BLOCKSPERSECOND;
if (TOCP[0] != ~0)
{
start = TOCL[TOCP[Track-1]];
end = TOCL[TOCP[Track]];
}
else
{
start = TOCL[Track-1];
end = TOCL[Track];
}
if (address >= start && address < end)
{
command.b2 = (address & 0xff000000) >> 24;
command.b3 = (address & 0x00ff0000) >> 16;
command.b4 = (address & 0x0000ff00) >> 8;
command.b5 = (address & 0x000000ff);
#ifdef SINGLE_TRACK_PLAY
length = end - address - 1;
command.b6 = (length & 0xff000000) >> 24;
command.b7 = (length & 0x00ff0000) >> 16;
command.b8 = (length & 0x0000ff00) >> 8;
command.b9 = (length & 0x000000ff);
#else
command.b6 = 0xff;
command.b7 = 0xff;
command.b8 = 0xff;
command.b9 = 0xff;
#endif
DoSCSI( DataBuf, DATA_LEN, &command, sizeof(command), (SCSIF_READ|SCSIF_AUTOSENSE) );
}
}
}
ULONG
Snoop_SCSI(ULONG *track, ULONG *tracktime, ULONG *time, ULONG ostat)
{
static SCSICMD10 command = { SCSI_CD_READ_SUB_CHANNEL };
command.b2 = 0x40;
command.b3 = 1;
command.b6 = 0;
command.b7 = 255;
command.b8 = 255;
/* snoop and update current status */
if (!DoSCSI( DataBuf, DATA_LEN, &command, sizeof(command), (SCSIF_READ|SCSIF_AUTOSENSE) ))
{
ULONG status;
ULONG address;
address = (DataBuf[8] << 24 | DataBuf[9] << 16 | DataBuf[10] << 8 | DataBuf[11]);
if (DataBuf[1] == 0x11)
{
#ifndef SINGLE_TRACK_PLAY
if (address >= EndAddress)
{
CD_Play(Track + 1); /* end of track, continue program */
return CD_Snoop(track, tracktime, time, CDP_STOPPED);
}
#endif
status = CDP_PLAYING;
}
else
if (DataBuf[1] == 0x12)
status = CDP_PAUSED;
else
{
if (JustStarted && !(DataBuf[5] & 0x04 /* signifies a data track */))
{
/* kludge for aborted PLAY_AUDIO (needed with Toshiba XM3601B) */
CD_Play(Track); /* restart track */
return CD_Snoop(track, tracktime, time, CDP_STOPPED);
}
else
if (ostat == CDP_PLAYING)
{
CD_Play(Track + 1); /* end of track, continue */
return CD_Snoop(track, tracktime, time, CDP_STOPPED);
}
JustStarted = FALSE;
*track = Track = 0;
return CDP_STOPPED;
}
Track = *track = DataBuf[6];
*time = address / BLOCKSPERSECOND;
address = (DataBuf[12] << 24 | DataBuf[13] << 16 | DataBuf[14] << 8 | DataBuf[15]);
*tracktime = address / BLOCKSPERSECOND;
if (*tracktime > 1) /* if the player managed to stay on for longer than */
JustStarted = FALSE; /* one second, we can assume it will do so. */
return status;
}
return (ULONG)(Ejected ? CDP_EJECTED : CDP_EMPTY);
}
ULONG
ReadTOC_SCSI(void)
{
static SCSICMD10 command = { SCSI_CD_READ_TOC };
command.b7 = 0x03;
command.b8 = 0x24;
/* Read track lengths from the CD Table Of Contents */
if (!DoSCSI( TOCBuf, TOC_LEN, &command, sizeof(command), (SCSIF_READ|SCSIF_AUTOSENSE) ))
{
ULONG tocsize = (TOCBuf[0] << 8) | TOCBuf[1];
ULONG tracks = 0;
UBYTE *toc;
if (tocsize > 2) tocsize -= 2;
for (toc = &TOCBuf[4] ; toc < (&TOCBuf[4] + tocsize) ; toc += 8 )
{
TOCL[tracks] = (toc[4] << 24) | (toc[5] << 16) | (toc[6] << 8) | (toc[7]);
TOCT[tracks] = TOCL[tracks] / BLOCKSPERSECOND;
TOCF[tracks] = (toc[1] & 0x04) ? 1 : 0;
TOCS[tracks] = &TitleBuffer[(tracks+2)*40];
Sprintf(TOCS[tracks], GS(TRACK_NUM), tracks+1);
tracks++;
}
TOCS[--tracks] = NULL;
if (!GetIndex( tracks, TOCL[2], TOCL[tracks]))
{
TITLE[0] = NULL;
TITLE[1] = NULL;
}
if (!TITLE[0])
{
TITLE[0] = &TitleBuffer[0];
strcpy(TITLE[0], GS(UNKNOWN_ARTIST));
}
if (!TITLE[1])
{
TITLE[1] = &TitleBuffer[40];
strcpy(TITLE[1], GS(UNKNOWN_TITLE));
}
return tracks;
}
if (SenseData[2] == 0x06 && /* media changed */
SenseData[7] >= 3 && /* enough sense data */
SenseData[12] == 0x28) /* media changed */
{
Delay(10);
return CD_ReadTOC();
}
return 0;
}
BOOL
IsCD_SCSI(void)
{
static SCSICMD6 command = { SCSI_INQUIRY };
/* Test if a SCSI target is a CD-ROM device */
command.b4 = 40;
if (!DoSCSI( DataBuf, DATA_LEN, &command, sizeof(command), (SCSIF_READ|SCSIF_AUTOSENSE) ))
{
return (BOOL)(((DataBuf[0] & 0x1f) == 0x05) ? TRUE : FALSE); /* is a CD-ROM */
}
return FALSE;
}